package data

import (
	"bytes"
	"crypto/sha1"
	"database/sql"
	"fmt"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql"
	"strings"
	"time"
)

const (
	passwd_salt            = `@*%^^@IL;ldo123`
	Mbr_no_role_type       = "0"
	Mbr_cargo_owner_type   = "1"
	Mbr_carrier_owner_type = "2"
	Mbr_logistics_type     = "3"
)

type MemberDto struct {
	Id        int    `orm:"pk; auto; column(id)`
	Name      string `orm:"column(name)"`
	NickName  string `orm:"column(nick_name)"`
	Passwd    string `orm:"column(password)"`
	Phone     string `orm:"column(phone)"`
	TypeId    int    `orm:"column(type_id)"`
	State     int    `orm:"column(state)"`
	Level     int    `orm:"column(level)"`
	AuthLevel int    `orm:"column(auth_level)"`
	Inviter   int    `orm:"column(inviter_id)"`
	PhotoUrl  string `orm:"column(photo)"`
	QRCode    string `orm:"column(qrcode)"`
	IDCardFS  string `orm:"column(id_card_fs)"`
	IDCardRS  string `orm:"column(id_card_rs)"`
	IDCardNo  string `orm:"column(id_card_no)"`
}

type LogisticsEmpDto struct {
	Id     int    `orm:"pk;column(id)"`
	CorpId int    `orm:"column(corp_id)"`
	Intro  string `orm:"column(intro)"`
}

type LoginLogDto struct {
	Id         int    `orm:"pk;column(id)"`
	MemberId   int    `orm:"column(member_id)"`
	RegisterId string `orm:"column(register_id)"`
	LogType    int    `orm:"column(log_type)"`
	Platform   string `orm:"column(platform)"`
}

type MemberRepo struct{}

func (m *MemberDto) TableName() string {
	return "m_member"
}

func (e *LogisticsEmpDto) TableName() string {
	return "m_logistics_emp"
}

func (l *LoginLogDto) TableName() string {
	return "m_login_log"
}

func (r MemberRepo) Exists(phone string) (exists bool, err error) {
	var num int64
	var list orm.ParamsList
	o := orm.NewOrm()
	num, err = o.Raw(SQL_Mbr_Exists, phone).ValuesFlat(&list)
	exists = num >= 1
	return
}

func (r MemberRepo) AddMember(dto *MemberDto) (id int64, err error) {
	o := orm.NewOrm()
	dto.Passwd = fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprintf("%s%s", dto.Passwd, passwd_salt))))
	id, err = o.Insert(dto)
	return
}

func (r MemberRepo) UpdateMemberClientInfo(memberId int, reigsterId, platform string) error {
	o := orm.NewOrm()
	_, err := o.Raw(SQL_Mbr_Upd_Client_Info, reigsterId, platform, memberId).Exec()
	return err
}

func (r MemberRepo) VerifyCode(phone, code string) (ok bool, err error) {
	var num int64
	var list orm.ParamsList
	o := orm.NewOrm()
	nowStr := time.Now().Format("2006-01-02 15:04:05")
	before5mStr := time.Now().Add(-time.Duration(5) * time.Minute).Format("2006-01-02 15:04:05")
	num, err = o.Raw(SQL_Mbr_Check_VerifyCode_Valid, phone, code, before5mStr, nowStr).ValuesFlat(&list)
	ok = err == nil && num >= 1
	if ok {
		o.Raw(SQL_Mbr_Invalid_VerifyCode, phone, code).Exec()
	}
	return
}

func (r MemberRepo) AddCode(phone, code string) (ok bool, err error) {
	var num int64
	var result sql.Result
	var list orm.ParamsList
	o := orm.NewOrm()
	nowStr := time.Now().Format("2006-01-02 15:04:05")
	before5mStr := time.Now().Add(-time.Duration(5) * time.Minute).Format("2006-01-02 15:04:05")
	num, err = o.Raw(SQL_Mbr_Check_VerifyCode_Not_Sent, phone, before5mStr, nowStr).ValuesFlat(&list)
	if num == 0 && err == nil {
		result, err = o.Raw(SQL_Mbr_Insert_VerifyCode, phone, code, 1, time.Now().Hour()).Exec()
		if err == nil {
			num, err = result.RowsAffected()
			ok = err == nil && num >= 1
		}
	}

	return
}

func (r MemberRepo) CheckPhoneAndPasswd(phone, passwd string) (mbr MemberDto, err error) {
	o := orm.NewOrm()
	pwd := fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprintf("%s%s", passwd, passwd_salt))))
	err = o.Raw(SQL_Mbr_Check_Phone_And_Passwd, phone, pwd).QueryRow(&mbr)
	return
}

func (r MemberRepo) AddQRCode(id int, qrcodeUrl string) (ok bool, err error) {
	var num int64
	var result sql.Result
	o := orm.NewOrm()
	result, err = o.Raw(SQL_Mbr_Upd_QRCode, qrcodeUrl, id).Exec()
	if err == nil {
		num, err = result.RowsAffected()
		ok = err == nil && num >= 1
	}
	return
}

func (r MemberRepo) GetMemberInfo(id int) (m MemberDto, err error) {
	m = MemberDto{Id: id}
	o := orm.NewOrm()
	err = o.Read(&m)
	return
}

func (r MemberRepo) GetMemberBriefInfo(ids []int) (list []MemberDto, err error) {
	o := orm.NewOrm()
	var buffer bytes.Buffer
	for _, id := range ids {
		buffer.WriteString(fmt.Sprintf("%d,", id))
	}
	_, err = o.Raw(fmt.Sprintf(SQL_Mbr_Get_Brief_Info, strings.TrimRight(buffer.String(), ","))).QueryRows(&list)
	return
}

func (r MemberRepo) UpdatePasswd(phone, passwd string) (ok bool, err error) {
	var num int64
	var result sql.Result
	o := orm.NewOrm()
	passwd = fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprintf("%s%s", passwd, passwd_salt))))
	result, err = o.Raw(SQL_Mbr_Upd_Passwd, passwd, phone).Exec()
	if err == nil {
		num, err = result.RowsAffected()
		ok = err == nil && num >= 1
	}
	return
}

func (r MemberRepo) UpdateEmp(dto *LogisticsEmpDto) error {
	mbr := &MemberDto{Id: dto.Id, TypeId: 3}
	o := orm.NewOrm()
	_, err := o.Update(dto)
	if err == nil {
		if err := r.UpdateAuthState(dto.Id, 4); err == nil {
			if mbrType, err := r.GetMemberType(dto.Id); err == nil {
				if mbrType == "0" {
					_, err = o.Update(mbr, "TypeId")
					return err
				}
			}
		}
	}

	return err
}

func (r MemberRepo) AddLoginLog(memberId, logType int, registerId, platform string) error {
	o := orm.NewOrm()
	_, err := o.Insert(&LoginLogDto{MemberId: memberId, LogType: logType, RegisterId: registerId, Platform: platform})
	return err
}

func (r MemberRepo) GetLoginRegisterId(memberId int) (registerId, platform string) {
	var list orm.ParamsList
	o := orm.NewOrm()
	if num, _ := o.Raw(SQL_Mbr_Get_RegisterId, memberId).ValuesFlat(&list); num >= 1 {
		registerId = list[0].(string)
		platform = list[1].(string)
	}
	return
}

func init() {
	orm.RegisterModel(new(MemberDto), new(LogisticsEmpDto), new(LoginLogDto))
}
